package org.aseclipse.osgi.container;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.Bundle;
import org.w3c.dom.Document;

public class ASBundleManager implements IASBundleManager {
	
	private static final Log log_ = LogFactory.getLog(ASBundleManager.class);
	
	private Map<String, ASBundle> asbundleCache_;
	private static ASBundleManager instance_;
	
	private Map<String, List<String>> extenderPluginNames_ = new HashMap<String, List<String>>();// key is bundle id, value is its extender plugin xml set;
	private Map<String, byte[]> extenderPlugins_ = new HashMap<String, byte[]>();// key is bundle id, value is its extender plugin xml set;
	
	private ASBundleManager() {
		asbundleCache_ = new HashMap<String, ASBundle>();
	}
	
	public static ASBundleManager getInstance() {
		if(instance_ == null)
			instance_ = new ASBundleManager();
		return instance_;
	}
	
	public ASBundle getBundle(String bundleName) {
		if(asbundleCache_.containsKey(bundleName)) {
			return asbundleCache_.get(bundleName);
		}
		return null;
	}

	synchronized public void process(Bundle bundle) {
		String name = bundle.getSymbolicName();
		if(asbundleCache_.containsKey(name)) {
			asbundleCache_.remove(name);
			log_.debug("Bundle '"+name+"' already exist, remove original cache");
		}
		try {
			ASBundle bundl = new ASBundle();
			bundl.init(bundle);
			asbundleCache_.put(name, bundl);
			List<String> extensions = bundl.getExtensions();
			if(extensions != null && extensions.size() > 0) {
				for(String key:extensions) {
					List<String> names =  extenderPluginNames_.get(key);
					if(names == null) {
						names = new ArrayList<String>();
						extenderPluginNames_.put(key, names);
					}
					if(!names.contains(bundl.getName())) {
						names.add(bundl.getName());
					}
				}
			}
			if(log_.isDebugEnabled()) {
				log_.debug(bundl.toString());
			}
		} catch(Exception ex) {
			log_.warn("Fail to handle "+bundle.getSymbolicName(), ex);
		}
	}
	
	public byte[] loadResource(String bundleName, String resourcePath, Map paramters) {
		if(asbundleCache_.containsKey(bundleName)) {
			ASBundle bund = asbundleCache_.get(bundleName);
			if(ASBundle.MANIFEST_NAME.equalsIgnoreCase(resourcePath)) {
				return bund.getManifest();
			} else if(ASBundle.MANIFEST_NAME.equalsIgnoreCase(resourcePath)) {
				return bund.getPluginXML();
			} else {
				return bund.getResource(resourcePath);
			}
		}
		return null;
	}
	
	public byte[] loadExtenderPlugins(String bundleName, Map paramters) {
		if(extenderPlugins_.containsKey(bundleName)) {
			return extenderPlugins_.get(bundleName);
		}
		log_.info("[loadExtenderPlugins] " + bundleName);
		ASBundle bundle = asbundleCache_.get(bundleName);
		List<String> points = bundle.getPoints();
		if(points == null && points.size() == 0) {
			return BundleUtil.EMPTY_PLUGINS_BODY;
		}
		Document root = BundleUtil.getEmptyPluginsResult();
		for(String point:points) {
			List<String> plugins = extenderPluginNames_.get(point);
			for(String plugin : plugins) { 
				byte[] data = asbundleCache_.get(plugin).getPluginXML();
				BundleUtil.fillBody(root, data);
			}
		}
		byte[] cache = BundleUtil.unparse(root);
		extenderPlugins_.put(bundleName, cache);
		return cache;
	}
	
	public byte[] loadRequiredPlugins(String bundleName, Map paramters) {
		return null;
	}
}
